﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Gunningine
{
    public class Battery
    {
        /// <summary>
        /// Temporary holding place for new objects.
        /// </summary>
        private List<Emitted> spawned = new List<Emitted>();

        /// <summary>
        /// Number of alive objects.
        /// </summary>
        protected int objectCount;

        /// <summary>
        /// Main list of objects.
        /// </summary>
        protected Emitted[] objects { get; private set; }

        /// <summary>
        /// Constructor.
        /// </summary>
        public Battery(int initialSize)
        {
            this.objects = new Emitted[initialSize];
            for (int i = 0; i < initialSize; ++i)
                this.objects[i] = null;

            this.objectCount = 0;
        }

        /// <summary>
        /// Reallocates memory for projectile storage.
        /// </summary>
        /// <param name="targetSize">desired new size.</param>
        private void ReallocateStorage(int targetSize)
        {
            int doubleSize = this.objects.Length * 2;
            int newSize = targetSize > doubleSize ? targetSize : doubleSize;

            Emitted[] newStorage = new Emitted[newSize];
            Array.Copy(this.objects, newStorage, this.objectCount);
            this.objects = newStorage;
        }

        /// <summary>
        /// Add newly-spawed projectiles.
        /// </summary>
        private void AddNewlySpawnedObjects()
        {
            int targetSize = this.objectCount + this.spawned.Count;
            if (targetSize > this.objects.Length)
                ReallocateStorage(targetSize);

            foreach (Emitted p in this.spawned)
            {
                this.objects[this.objectCount++] = p;
            }

            this.spawned.Clear();
        }

        /// <summary>
        /// Emit an object.
        /// </summary>
        public void Add(Emitted emitted)
        {
            this.spawned.Add(emitted);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="frameTime"></param>
        public void Update(float frameTime, object userParams)
        {
            AddNewlySpawnedObjects();

            // Go over all objects, and update (or kill)
            int eCount = 0;
            for (int i = 0; i < this.objectCount; ++i)
            {
                var emittedObj = this.objects[i];

                if (emittedObj.Alive)
                {
                    // If emitted is active, update it.
                    emittedObj.Update(frameTime);
                }
                else
                {
                    continue;
                }

			    if (i != eCount)
                    this.objects[eCount] = emittedObj;

			    eCount++;
            }

            this.objectCount = eCount;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="renderSystem"></param>
        public void Render(RenderSystem renderSystem)
        {
            for (int i = 0; i < this.objectCount; ++i)
            {
                var emittedObj = this.objects[i];

                if (emittedObj.Alive)
                {
                }
            }
        }
    }
}
